package com.hg.oa.common.restful;

import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.util.Log;

import com.hg.oa.util.FileUtils;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.util.Arrays;
import java.util.Collection;
import java.util.concurrent.TimeUnit;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;

import okhttp3.Cache;
import okhttp3.CacheControl;
import okhttp3.HttpUrl;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okio.Buffer;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

/**
 * Created by fxa on 2016/6/21.
 */

public class RestClient {

    public static String CACHE_DIR;
    static String tag = "RestClient";
    static String scheme = "https";
    static String host = "192.168.100.126";
    static int port = 8443;
    static Retrofit retrofit;
    static OkHttpClient okHttpClient;
    static Context context;

    public static void init(Context context) {
        RestClient.context = context;
        CACHE_DIR = context.getPackageName();
        getRetrofitInstance();
    }


    /**
     * 创建Retrofit 客户端
     *
     * @return
     */
    public static Retrofit getRetrofitInstance() {
        if (retrofit == null) {
            HttpUrl.Builder builder = new HttpUrl.Builder();
            builder.scheme(scheme);
            builder.host(host);
            builder.port(port);
            retrofit = new Retrofit.Builder()
                    .baseUrl(builder.build())
                    .addConverterFactory(GsonConverterFactory.create())
                    .client(getOkHttpClient())
                    .build();
        }
        return retrofit;
    }


    public static OkHttpClient getOkHttpClient() {
        if (okHttpClient == null) {
            File cacheFile = new File(FileUtils.SD_PATH + CACHE_DIR, "cache");
            Cache cache = new Cache(cacheFile, 1024 * 1024 * 100); //100Mb
            OkHttpClient.Builder httpBuilder = new OkHttpClient.Builder();
            okHttpClient = httpBuilder.
                    readTimeout(1, TimeUnit.MINUTES)
                    .connectTimeout(1, TimeUnit.MINUTES)
                    .writeTimeout(3, TimeUnit.MINUTES) //设置超时
                    .retryOnConnectionFailure(true)
                    .hostnameVerifier(new HostnameVerifier() {
                        @Override
                        public boolean verify(String hostname, SSLSession session) {
                            Log.e(tag, "hostname-->" + hostname);
                            return true;
                        }
                    })
                    .sslSocketFactory(getSocketFactory(), trustManager)
                    .cache(cache)
                    .addNetworkInterceptor(interceptor)
                    .addInterceptor(interceptor)
                    .build();
        }
        return okHttpClient;
    }

    /**
     * 创建rest对象
     *
     * @param clazz
     * @param <T>
     * @return
     */
    public static <T> T createRest(Class<T> clazz) {
        return getRetrofitInstance().create(clazz);
    }


    static Interceptor interceptor = new Interceptor() {
        @Override
        public Response intercept(Chain chain) throws IOException {
            Request request = chain.request();
            if (!isNetworkAvailable(context)) {
                request = request.newBuilder()
                        .cacheControl(CacheControl.FORCE_CACHE)
                        .build();
                Log.e(tag, "no network");
            }
            Response originalResponse = chain.proceed(request);
            if (isNetworkAvailable(context)) {
                Log.e(tag, "on network cache1");
                //有网的时候读接口上的@Headers里的配置，你可以在这里进行统一的设置
                String cacheControl = request.cacheControl().toString();
                return originalResponse.newBuilder()
                        .header("Cache-Control", cacheControl)
                        .removeHeader("Pragma")
                        .build();
            } else {
                Log.e(tag, "no network cache1");
                return originalResponse.newBuilder()
                        .header("Cache-Control", "public, only-if-cached, max-stale=2419200")
                        .removeHeader("Pragma")
                        .build();
            }
        }
    };


    public static boolean isNetworkAvailable(Context context) {
        ConnectivityManager cm = (ConnectivityManager) context
                .getSystemService(Context.CONNECTIVITY_SERVICE);
        if (cm == null) {
        } else {

            NetworkInfo[] info = cm.getAllNetworkInfo();
            if (info != null) {
                for (int i = 0; i < info.length; i++) {
                    if (info[i].getState() == NetworkInfo.State.CONNECTED) {
                        return true;
                    }
                }
            }
        }
        return false;
    }


    static X509TrustManager trustManager = null;

    private static SSLSocketFactory getSocketFactory() {
        try {
            trustManager = trustManagerForCertificates(trustedCertificatesInputStream());
            SSLContext sslContext = SSLContext.getInstance("TLS");
            sslContext.init(null, new TrustManager[]{trustManager}, null);
            return sslContext.getSocketFactory();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    private static InputStream trustedCertificatesInputStream() {
        return new Buffer()
                .writeUtf8(RSA_KEY)
                .inputStream();
    }

    private static X509TrustManager trustManagerForCertificates(InputStream in)
            throws GeneralSecurityException {
        CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
        Collection<? extends Certificate> certificates = certificateFactory.generateCertificates(in);
        if (certificates.isEmpty()) {
            throw new IllegalArgumentException("expected non-empty set of trusted certificates");
        }

        // Put the certificates a key store.
        char[] password = "password".toCharArray(); // Any password will work.
        KeyStore keyStore = newEmptyKeyStore(password);
        int index = 0;
        for (Certificate certificate : certificates) {
            String certificateAlias = Integer.toString(index++);
            keyStore.setCertificateEntry(certificateAlias, certificate);
        }

        // Use it to build an X509 trust manager.
        KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(
                KeyManagerFactory.getDefaultAlgorithm());
        keyManagerFactory.init(keyStore, password);
        TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(
                TrustManagerFactory.getDefaultAlgorithm());
        trustManagerFactory.init(keyStore);
        TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
        if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) {
            throw new IllegalStateException("Unexpected default trust managers:"
                    + Arrays.toString(trustManagers));
        }
        return (X509TrustManager) trustManagers[0];
    }


    private static KeyStore newEmptyKeyStore(char[] password) throws GeneralSecurityException {
        try {
            KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
            InputStream in = null; // By convention, 'null' creates an empty key store.
            keyStore.load(in, password);
            return keyStore;
        } catch (IOException e) {
            throw new AssertionError(e);
        }
    }


    static String RSA_KEY = "-----BEGIN CERTIFICATE-----\n" +
            "MIIDjzCCAnegAwIBAgIEP/8PHTANBgkqhkiG9w0BAQsFADB4MRIwEAYDVQQGEwlm\n" +
            "ZW5neGlhbmcxEjAQBgNVBAgTCWZlbmd4aWFuZzESMBAGA1UEBxMJZmVuZ3hpYW5n\n" +
            "MRIwEAYDVQQKEwlmZW5neGlhbmcxEjAQBgNVBAsTCWZlbmd4aWFuZzESMBAGA1UE\n" +
            "AxMJZmVuZ3hpYW5nMB4XDTE2MDkyODA2MzczNFoXDTE2MTIyNzA2MzczNFoweDES\n" +
            "MBAGA1UEBhMJZmVuZ3hpYW5nMRIwEAYDVQQIEwlmZW5neGlhbmcxEjAQBgNVBAcT\n" +
            "CWZlbmd4aWFuZzESMBAGA1UEChMJZmVuZ3hpYW5nMRIwEAYDVQQLEwlmZW5neGlh\n" +
            "bmcxEjAQBgNVBAMTCWZlbmd4aWFuZzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC\n" +
            "AQoCggEBAMWjiFBQJ/LwEFPu5q8LAAsgWWilWL3fZNJ03pUCUvt9EqFhOspJPNuf\n" +
            "RXxLQSOxYbogSzCG0PDGW1bSrAB0druG423y4hep5PXuIfLTW/H1FBz9WfEPj14T\n" +
            "DFewmpHDJ2K7HeWl3S4Bg+e52nbsjLB2iwtXt7cNwhRbemXkjP2Y5Kz4xElEbbG5\n" +
            "7b6wpjKDpovQ+jOCWbIxLAhpC5UnS6+QzW5ULz6YY3+PwblxwrxaFw5X1imB401u\n" +
            "eqpti2U+j3YTYVP9MmnLZsA0vVEai0vq1bLuHKzthHflXHt29dBgYn3fOPBE/ueQ\n" +
            "ty4H67AaD4g5b0plUU4uxiGurNiOHn0CAwEAAaMhMB8wHQYDVR0OBBYEFOZ4rnkP\n" +
            "jvq1+uuEUBKA1OPPuaerMA0GCSqGSIb3DQEBCwUAA4IBAQCUVerEsCczcD8n5fgj\n" +
            "K9KApx31E7WssN2vEGz8+BMlPh+DkUOPXtldp5YzBVOHkjvdy5vz3ZFHvd0aTNqc\n" +
            "dwhXhmEMgl0lVy0ymW1W+e3nWyh0IHiVHqK3h+XCqx8ZQbn0Eh7Fbif0O6pDbOKq\n" +
            "fzoBkJv7jpSRo6/aKSik9f9pyoIaZTHNynkZHjwt3kQTWcMxeGPJ9McZbOBr6oh/\n" +
            "gzzhMGpY0haM8lOhCiEKv2dXRjFRaGGSMRwTGxPsCMq816VGZrnhYCfo5Nl4ASOg\n" +
            "C5KS+QtOOVGepehOH6OivqdIuYBLnFYijm6vT7zMCapvYlhD0ea+tj6rTTVJpP8P\n" +
            "s7uJ\n" +
            "-----END CERTIFICATE-----";

}
